#include "data_collector.h"
#include "ns3/log.h"
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <filesystem>
#include <cmath>
#include <set>
#include <cstdlib>
#include <ctime>

namespace ns3 {

NS_LOG_COMPONENT_DEFINE("SimDataCollector");

DataCollector::DataCollector() 
  : m_dataManager(nullptr),
    m_nodeManager(nullptr),
    m_linkManager(nullptr),
    m_flowMonitor(nullptr)
{
  NS_LOG_FUNCTION(this);
  // 初始化随机数种子
  std::srand(std::time(nullptr));
}

DataCollector::~DataCollector() 
{
  NS_LOG_FUNCTION(this);
}

bool DataCollector::Initialize(const DataManager& dataManager, 
                              const NodeManager& nodeManager, 
                              const LinkManager& linkManager) 
{
  NS_LOG_FUNCTION(this);
  
  m_dataManager = &dataManager;
  m_nodeManager = &nodeManager;
  m_linkManager = &linkManager;
  
  return true;
}

bool DataCollector::SetupFlowMonitor() 
{
  NS_LOG_FUNCTION(this);
  
  // 创建流量监控器
  m_flowMonitor = m_flowMonitorHelper.InstallAll();
  
  if (!m_flowMonitor) {
    NS_LOG_ERROR("流量监控器创建失败");
    return false;
  }
  
  NS_LOG_INFO("已设置流量监控器");
  return true;
}

bool DataCollector::CollectData() 
{
  NS_LOG_FUNCTION(this);
  
  if (!m_flowMonitor) {
    NS_LOG_ERROR("流量监控器未设置");
    std::cout << "错误: 流量监控器未设置，无法收集数据" << std::endl;
    return false;
  }
  
  std::cout << "正在收集流量数据..." << std::endl;
  
  // 清空之前的统计信息
  m_flowStats.clear();
  
  // 获取流量统计数据
  m_flowMonitor->CheckForLostPackets();
  Ptr<Ipv4FlowClassifier> classifier = DynamicCast<Ipv4FlowClassifier>(m_flowMonitorHelper.GetClassifier());
  
  if (!classifier) {
    NS_LOG_ERROR("无法获取IPv4流分类器");
    return false;
  }
  
  // 获取流统计信息
  std::map<FlowId, FlowMonitor::FlowStats> stats = m_flowMonitor->GetFlowStats();
  
  for (auto it = stats.begin(); it != stats.end(); ++it) {
    FlowId flowId = it->first;
    FlowMonitor::FlowStats flowStats = it->second;
    
    // 获取流分类信息
    Ipv4FlowClassifier::FiveTuple tuple = classifier->FindFlow(flowId);
    
    // 创建流量统计结构
    FlowStats fs;
    fs.flowId = flowId;
    
    // 识别流中的节点
    if (!IdentifyFlowNodes(flowId, tuple.sourceAddress, tuple.destinationAddress, fs)) {
      NS_LOG_WARN("无法识别流 " << flowId << " 中的节点");
      continue;
    }
    
    // 计算统计指标
    fs.txPackets = flowStats.txPackets;
    fs.rxPackets = flowStats.rxPackets;
    fs.lostPackets = flowStats.txPackets - flowStats.rxPackets;
    
    if (flowStats.txPackets > 0) {
      fs.packetLossRatio = double(fs.lostPackets) / double(flowStats.txPackets);
    } else {
      fs.packetLossRatio = 0.0;
    }
    
    // 计算吞吐量 (bits/s)
    double durationSeconds = (flowStats.timeLastRxPacket - flowStats.timeFirstTxPacket).GetSeconds();
    if (durationSeconds > 0) {
      fs.throughput = (flowStats.rxBytes * 8.0) / durationSeconds;
    } else {
      fs.throughput = 0;
    }
    
    // 计算平均延迟和抖动
    if (flowStats.rxPackets > 0) {
      fs.meanDelay = flowStats.delaySum.GetSeconds() / flowStats.rxPackets;
      fs.meanJitter = flowStats.jitterSum.GetSeconds() / flowStats.rxPackets;
    } else {
      fs.meanDelay = 0;
      fs.meanJitter = 0;
    }
    
    // 添加到统计集合
    m_flowStats.push_back(fs);
    
    // 输出统计信息
    NS_LOG_INFO("流 " << flowId << ": " << GenerateStatsString(fs));
  }
  
  NS_LOG_INFO("已收集 " << m_flowStats.size() << " 条流量统计信息");
  return true;
}

void DataCollector::GenerateTimePointData(uint32_t vehicleId, const std::vector<VehicleData>& trajectory) 
{
  NS_LOG_FUNCTION(this << vehicleId << trajectory.size());
  
  if (!m_linkManager) {
    NS_LOG_ERROR("链接管理器未初始化");
    return;
  }
  
  // 清空之前的时间点数据
  m_vehicleTimePoints.clear();
  
  // 获取所有地面基站和卫星连接
  const auto& gsConnections = m_linkManager->GetGroundStationConnections();
  const auto& satConnections = m_linkManager->GetSatelliteConnections();
  
  // 为每个车辆位置时间点生成性能数据
  for (const auto& vehicleData : trajectory) {
    // 不限制处理的时间点数量，处理所有轨迹数据点
    // 如果数据量太大可能需要重新考虑限制策略
    
    // 创建车辆时间点数据
    VehicleTimePointData timePointData;
    timePointData.time = vehicleData.time;
    timePointData.position = vehicleData.position;
    timePointData.speed = vehicleData.speed;
    
    // 收集当前时间点的性能数据
    
    // 1. 为每个地面基站创建性能数据
    for (const auto& entry : gsConnections) {
      uint32_t gsId = entry.first;
      
      // 基于现有流量统计或构建默认统计
      FlowStats stats;
      stats.sourceNodeId = vehicleId;
      stats.destinationNodeId = gsId;
      stats.nodeType = "GroundStation";
      
      // 计算当前位置下车辆与基站的距离
      stats.distance = CalculateDistance(vehicleData.position, "GroundStation", gsId);
      
      // 根据距离调整性能参数
      // 如果距离超过3.5km（扩大的地面基站覆盖范围），则设为完全连接失败
      if (stats.distance > 3500.0) {
        stats.txPackets = 100;
        stats.rxPackets = 0;
        stats.lostPackets = 100;
        stats.packetLossRatio = 1.0;
        stats.throughput = 0.0;
        stats.meanDelay = 0.0;
        stats.meanJitter = 0.0;
        stats.connected = false; // 设置为未连接状态
      } else {
        // 根据距离计算性能衰减
        double distanceFactor = std::max(0.0, 1.0 - stats.distance / 3500.0);
        
        // 为简化起见，使用距离因子生成一些模拟的性能数据
        stats.txPackets = 100;
        stats.rxPackets = static_cast<uint32_t>(100 * distanceFactor);
        stats.lostPackets = 100 - stats.rxPackets;
        stats.packetLossRatio = static_cast<double>(stats.lostPackets) / 100.0;
        stats.throughput = 1000000 * distanceFactor; // 最大1Mbps
        stats.meanDelay = 0.01 * (1.0 / distanceFactor); // 距离越远延迟越高
        stats.meanJitter = 0.002 * (1.0 / distanceFactor);
        
        // 如果接收到的包数大于0，则认为已连接
        stats.connected = (stats.rxPackets > 0);
      }
      
      // 添加到当前时间点的性能数据
      timePointData.flowStats.push_back(stats);
    }
    
    // 2. 为每个卫星创建性能数据
    for (const auto& entry : satConnections) {
      uint32_t satId = entry.first;
      
      // 创建性能数据
      FlowStats stats;
      stats.sourceNodeId = vehicleId;
      stats.destinationNodeId = satId;
      stats.nodeType = "Satellite";
      
      // 计算当前位置下车辆与卫星的距离
      stats.distance = CalculateDistance(vehicleData.position, "Satellite", satId);
      
      // 卫星通信的性能受距离影响较小，但延迟较高，添加一些随机干扰因素
      stats.txPackets = 100;
      
      // 添加随机干扰因素，使卫星连接不再是100%稳定
      double interferenceRatio = 0.05 + (std::rand() % 100) / 1000.0; // 5%-15%的干扰率
      stats.rxPackets = static_cast<uint32_t>(100 * (1.0 - interferenceRatio));
      stats.lostPackets = 100 - stats.rxPackets;
      stats.packetLossRatio = static_cast<double>(stats.lostPackets) / 100.0;
      stats.throughput = 500000 * (1.0 - interferenceRatio); // 基础500kbps受干扰影响
      stats.meanDelay = (stats.distance / 299792458.0) * (1.0 + interferenceRatio); // 光速传播延迟基础上增加干扰
      stats.meanJitter = 0.001 * (1.0 + 2.0 * interferenceRatio);
      stats.connected = true; // 卫星通信虽有干扰但仍保持连接
      
      // 添加到当前时间点的性能数据
      timePointData.flowStats.push_back(stats);
    }
    
    // 将时间点数据添加到集合
    m_vehicleTimePoints.push_back(timePointData);
  }
  
  NS_LOG_INFO("已为车辆 " << vehicleId << " 生成 " << m_vehicleTimePoints.size() 
             << " 个时间点的性能数据，每个时间点 " 
             << (m_vehicleTimePoints.empty() ? 0 : m_vehicleTimePoints[0].flowStats.size()) 
             << " 条连接记录");
}

double DataCollector::CalculateDistance(const Vector& vehiclePos, const std::string& nodeType, uint32_t nodeId) const 
{
  if (!m_nodeManager) {
    return -1.0;
  }
  
  Ptr<Node> targetNode = nullptr;
  
  if (nodeType == "GroundStation") {
    targetNode = m_nodeManager->GetGroundStationNode(nodeId);
  } else if (nodeType == "Satellite") {
    targetNode = m_nodeManager->GetSatelliteNode(nodeId);
  }
  
  if (!targetNode) {
    return -1.0;
  }
  
  Ptr<MobilityModel> mobility = targetNode->GetObject<MobilityModel>();
  if (!mobility) {
    return -1.0;
  }
  
  Vector targetPos = mobility->GetPosition();
  
  // 计算欧氏距离
  double dx = vehiclePos.x - targetPos.x;
  double dy = vehiclePos.y - targetPos.y;
  double dz = vehiclePos.z - targetPos.z;
  
  return std::sqrt(dx*dx + dy*dy + dz*dz);
}

bool DataCollector::SaveData(uint32_t vehicleId, const std::string& outputDir) 
{
  NS_LOG_FUNCTION(this << vehicleId << outputDir);
  
  if (!m_dataManager) {
    NS_LOG_ERROR("数据管理器未初始化");
    return false;
  }

  // 获取车辆轨迹数据
  std::cout << "获取车辆 " << vehicleId << " 的轨迹数据..." << std::endl;
  const std::vector<VehicleData> vehicleTrajectory = m_dataManager->GetVehicleTrajectory(vehicleId);
  if (vehicleTrajectory.empty()) {
    NS_LOG_ERROR("未找到车辆 " << vehicleId << " 的轨迹数据");
    std::cout << "错误: 未找到车辆 " << vehicleId << " 的轨迹数据!" << std::endl;
    return false;
  }
  
  std::cout << "处理车辆 " << vehicleId << " 的 " << vehicleTrajectory.size() << " 个时间点数据..." << std::endl;
  // 处理每个时间点的数据
  GenerateTimePointData(vehicleId, vehicleTrajectory);
  
  // 确保输出目录存在
  std::filesystem::create_directories(outputDir);
  
  // 只创建详细的性能数据文件
  std::string detailedFilename = outputDir + "/vehicle_" + std::to_string(vehicleId) + "_detailed_performance.csv";
  std::ofstream detailedFile(detailedFilename);
  
  if (!detailedFile) {
    NS_LOG_WARN("无法创建详细性能数据文件 " << detailedFilename);
    return true; // 主文件已保存成功，所以仍然返回true
  }
  
  // 写入详细CSV头
  detailedFile << "vehicle_id,time,x,y,z,speed,node_id,node_type,distance,tx_packets,rx_packets,lost_packets,"
               << "packet_loss_ratio,throughput,mean_delay,mean_jitter,connected" << std::endl;
  
  size_t detailedRecords = 0;
  
  // 对于每个时间点
  for (size_t i = 0; i < m_vehicleTimePoints.size(); ++i) {
    const auto& timePoint = m_vehicleTimePoints[i];
    
    // 记录已处理的节点，避免重复
    std::set<std::pair<std::string, uint32_t>> processedNodes;
    
    // 对于每个连接（基站或卫星）
    for (const auto& stats : timePoint.flowStats) {
      // 跳过重复的节点
      std::pair<std::string, uint32_t> nodeKey(stats.nodeType, stats.destinationNodeId);
      if (processedNodes.find(nodeKey) != processedNodes.end()) {
        continue;
      }
      
      processedNodes.insert(nodeKey);
      
      // 写入数据行
      detailedFile << vehicleId << ","
                  << std::fixed << std::setprecision(6) << timePoint.time << ","
                  << std::fixed << std::setprecision(6) << timePoint.position.x << ","
                  << std::fixed << std::setprecision(6) << timePoint.position.y << ","
                  << std::fixed << std::setprecision(6) << timePoint.position.z << ","
                  << std::fixed << std::setprecision(6) << timePoint.speed << ","
                  << stats.destinationNodeId << ","
                  << stats.nodeType << ","
                  << stats.distance << ","
                  << stats.txPackets << ","
                  << stats.rxPackets << ","
                  << stats.lostPackets << ","
                  << std::fixed << std::setprecision(6) << stats.packetLossRatio << ","
                  << stats.throughput << ","
                  << stats.meanDelay << ","
                  << stats.meanJitter << ","
                  << (stats.connected ? "1" : "0") 
                  << std::endl;
      
      detailedRecords++;
    }
  }
  
  detailedFile.close();
  
  NS_LOG_INFO("已将详细性能数据保存到 " << detailedFilename << "，包含 " << detailedRecords << " 条记录，"
              << m_vehicleTimePoints.size() << " 个时间点，每个时间点平均 " 
              << (m_vehicleTimePoints.empty() ? 0 : detailedRecords / m_vehicleTimePoints.size()) << " 条记录");
  
  // 输出到控制台
  std::cout << "详细性能数据已保存到 " << detailedFilename << std::endl;
  std::cout << "- 总记录数: " << detailedRecords << std::endl;
  std::cout << "- 时间点数: " << m_vehicleTimePoints.size() << std::endl;
  std::cout << "- 每个时间点平均记录数: " 
            << (m_vehicleTimePoints.empty() ? 0 : detailedRecords / m_vehicleTimePoints.size()) << std::endl;
  
  // 统计连接状态信息
  int totalConnections = 0;
  int successConnections = 0;
  
  for (const auto& timePoint : m_vehicleTimePoints) {
    for (const auto& stat : timePoint.flowStats) {
      totalConnections++;
      if (stat.connected) {
        successConnections++;
      }
    }
  }
  
  if (totalConnections > 0) {
    double connectivityRate = 100.0 * successConnections / totalConnections;
    std::cout << "- 连接成功率: " << std::fixed << std::setprecision(2) 
              << connectivityRate << "% (" << successConnections << "/" << totalConnections << ")" << std::endl;
  }

  // 计算并显示更多综合性能指标
  std::cout << "\n========== 车辆 " << vehicleId << " 性能总结 ==========" << std::endl;
  
  // 分开计算地面基站和卫星的连接性能
  double gsAvgThroughput = 0.0;
  double gsAvgDelay = 0.0;
  double gsAvgPacketLoss = 0.0;
  int gsConnections = 0;
  int gsSuccessConnections = 0;
  
  double satAvgThroughput = 0.0;
  double satAvgDelay = 0.0;
  double satAvgPacketLoss = 0.0;
  int satConnections = 0;
  int satSuccessConnections = 0;
  
  // 计算每种连接类型的平均性能
  for (const auto& timePoint : m_vehicleTimePoints) {
    for (const auto& stat : timePoint.flowStats) {
      if (stat.nodeType == "GroundStation") {
        gsConnections++;
        if (stat.connected) {
          gsSuccessConnections++;
          gsAvgThroughput += stat.throughput;
          gsAvgDelay += stat.meanDelay;
          gsAvgPacketLoss += stat.packetLossRatio;
        }
      } else if (stat.nodeType == "Satellite") {
        satConnections++;
        if (stat.connected) {
          satSuccessConnections++;
          satAvgThroughput += stat.throughput;
          satAvgDelay += stat.meanDelay;
          satAvgPacketLoss += stat.packetLossRatio;
        }
      }
    }
  }
  
  // 计算地面基站平均值
  if (gsSuccessConnections > 0) {
    gsAvgThroughput /= gsSuccessConnections;
    gsAvgDelay /= gsSuccessConnections;
    gsAvgPacketLoss /= gsSuccessConnections;
    
    std::cout << "\n地面基站连接性能:" << std::endl;
    std::cout << "- 连接成功率: " << std::fixed << std::setprecision(2) 
              << (100.0 * gsSuccessConnections / gsConnections) << "% ("
              << gsSuccessConnections << "/" << gsConnections << ")" << std::endl;
    std::cout << "- 平均吞吐量: " << std::fixed << std::setprecision(2) 
              << (gsAvgThroughput / 1000) << " kbps" << std::endl;
    std::cout << "- 平均延迟: " << std::fixed << std::setprecision(2) 
              << (gsAvgDelay * 1000) << " ms" << std::endl;
    std::cout << "- 平均丢包率: " << std::fixed << std::setprecision(2) 
              << (gsAvgPacketLoss * 100) << "%" << std::endl;
  } else {
    std::cout << "\n地面基站连接性能: 无成功连接" << std::endl;
  }
  
  // 计算卫星平均值
  if (satSuccessConnections > 0) {
    satAvgThroughput /= satSuccessConnections;
    satAvgDelay /= satSuccessConnections;
    satAvgPacketLoss /= satSuccessConnections;
    
    std::cout << "\n卫星连接性能:" << std::endl;
    std::cout << "- 连接成功率: " << std::fixed << std::setprecision(2) 
              << (100.0 * satSuccessConnections / satConnections) << "% ("
              << satSuccessConnections << "/" << satConnections << ")" << std::endl;
    std::cout << "- 平均吞吐量: " << std::fixed << std::setprecision(2) 
              << (satAvgThroughput / 1000) << " kbps" << std::endl;
    std::cout << "- 平均延迟: " << std::fixed << std::setprecision(2) 
              << (satAvgDelay * 1000) << " ms" << std::endl;
    std::cout << "- 平均丢包率: " << std::fixed << std::setprecision(2) 
              << (satAvgPacketLoss * 100) << "%" << std::endl;
  } else {
    std::cout << "\n卫星连接性能: 无成功连接" << std::endl;
  }
  
  // 计算连接切换次数（从地面基站到卫星或反之）
  int connectionSwitches = 0;
  std::string lastConnType = "";
  
  for (size_t i = 0; i < m_vehicleTimePoints.size(); ++i) {
    const auto& timePoint = m_vehicleTimePoints[i];
    bool hasGroundStationConn = false;
    bool hasSatelliteConn = false;
    
    for (const auto& stat : timePoint.flowStats) {
      if (stat.connected) {
        if (stat.nodeType == "GroundStation") hasGroundStationConn = true;
        if (stat.nodeType == "Satellite") hasSatelliteConn = true;
      }
    }
    
    std::string currentConnType;
    if (hasGroundStationConn && hasSatelliteConn) currentConnType = "Both";
    else if (hasGroundStationConn) currentConnType = "GroundStation";
    else if (hasSatelliteConn) currentConnType = "Satellite";
    else currentConnType = "None";
    
    if (!lastConnType.empty() && currentConnType != lastConnType) {
      connectionSwitches++;
    }
    
    lastConnType = currentConnType;
  }
  
  std::cout << "\n连接切换次数: " << connectionSwitches << std::endl;
  std::cout << "=========================================" << std::endl;
  
  // 清理时间点数据，为下一次收集做准备
  m_vehicleTimePoints.clear();
  
  return true;
}

void DataCollector::Reset() 
{
  NS_LOG_FUNCTION(this);
  
  m_flowMonitor = nullptr;
  m_flowStats.clear();
  m_vehicleTimePoints.clear();
}

std::string DataCollector::GenerateStatsString(const FlowStats& stats) const 
{
  std::stringstream ss;
  
  ss << "车辆 -> " << stats.nodeType << " " << stats.destinationNodeId 
     << " (距离: " << stats.distance << "m)"
     << ", 发送: " << stats.txPackets 
     << ", 接收: " << stats.rxPackets 
     << ", 丢失: " << stats.lostPackets
     << ", 丢包率: " << std::fixed << std::setprecision(3) << stats.packetLossRatio * 100.0 << "%"
     << ", 吞吐量: " << stats.throughput / 1000.0 << " kbps"
     << ", 延迟: " << stats.meanDelay * 1000.0 << " ms"
     << ", 抖动: " << stats.meanJitter * 1000.0 << " ms";
  
  return ss.str();
}

bool DataCollector::IdentifyFlowNodes(uint32_t flowId, 
                                    Ipv4Address sourceAddress, 
                                    Ipv4Address destinationAddress,
                                    FlowStats& stats) const 
{
  if (!m_linkManager) {
    return false;
  }
  
  // 遍历所有地面基站连接
  const auto& gsConnections = m_linkManager->GetGroundStationConnections();
  for (const auto& entry : gsConnections) {
    uint32_t gsId = entry.first;
    const ConnectionInfo& conn = entry.second;
    
    // 检查IP地址匹配
    if (conn.ipIfaces.GetN() >= 2) {
      if ((sourceAddress == conn.ipIfaces.GetAddress(0) && 
           destinationAddress == conn.ipIfaces.GetAddress(1)) ||
          (sourceAddress == conn.ipIfaces.GetAddress(1) && 
           destinationAddress == conn.ipIfaces.GetAddress(0))) {
        
        // 填充统计信息
        stats.sourceNodeId = 0;  // 车辆ID总是0
        stats.destinationNodeId = gsId;
        stats.nodeType = "GroundStation";
        stats.distance = conn.distance;
        
        return true;
      }
    }
  }
  
  // 遍历所有卫星连接
  const auto& satConnections = m_linkManager->GetSatelliteConnections();
  for (const auto& entry : satConnections) {
    uint32_t satId = entry.first;
    const ConnectionInfo& conn = entry.second;
    
    // 检查IP地址匹配
    if (conn.ipIfaces.GetN() >= 2) {
      if ((sourceAddress == conn.ipIfaces.GetAddress(0) && 
           destinationAddress == conn.ipIfaces.GetAddress(1)) ||
          (sourceAddress == conn.ipIfaces.GetAddress(1) && 
           destinationAddress == conn.ipIfaces.GetAddress(0))) {
        
        // 填充统计信息
        stats.sourceNodeId = 0;  // 车辆ID总是0
        stats.destinationNodeId = satId;
        stats.nodeType = "Satellite";
        stats.distance = conn.distance;
        
        return true;
      }
    }
  }
  
  return false;
}

} // namespace ns3
